import 'dart:math' as math;

import 'package:flutter/material.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:three_js/three_js.dart' as three;
import 'package:three_js/three_js.dart' show MaterialProperty;

class ComVrHdr extends StatefulWidget {
  const ComVrHdr({super.key});

  @override
  State<ComVrHdr> createState() => _ComVrHdrState();
}

class _ComVrHdrState extends State<ComVrHdr> {
  late three.ThreeJS threeJs;
  late three.OrbitControls controls; // 视角控制
  double scaleMesh = 3.5; // 缩放箭头
  double gapK = 3; // 缩放箭头距离
  late three.Group fixedArrowGroup; // 箭头组

  List<String> get _currentSpace => genCubeUrls('assets/textures/', '.png');

  @override
  void initState() {
    threeJs = three.ThreeJS(
      onSetupComplete: () {
        setState(() {});
      },
      setup: setup,
    );
    super.initState();
  }

  @override
  void dispose() {
    threeJs.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(body: threeJs.build());
  }

  Future<void> setup() async {
    threeJs.scene = three.Scene();
    threeJs.camera = three.PerspectiveCamera(
      60,
      threeJs.width / threeJs.height,
      0.1,
      2000,
    );
    threeJs.camera.position = three.Vector3(0, 20, 0);
    // 控制器设置
    controls = three.OrbitControls(threeJs.camera, threeJs.globalKey);
    controls.target.setValues(0, 15, 0);
    controls.minDistance = 10;
    controls.maxDistance = 70;
    controls.minPolarAngle = math.pi / 4;
    controls.maxPolarAngle = math.pi;
    controls.enablePan = false;

    final cubeRenderTarget = three.WebGLCubeRenderTarget(256);
    final cubeCamera = three.CubeCamera(1, 500, cubeRenderTarget);

    // 立方体纹理
    three.CubeTextureLoader().fromAssetList(_currentSpace).then((cubeTexture) {
      threeJs.scene.background = cubeTexture;
      cubeCamera.update(threeJs.renderer!, threeJs.scene);
    });

    // 添加导航箭头
    final westArrow = await loadArrow(
      "west_zh",
      three.Vector3(-gapK, 0, 0),
      rotationX: -math.pi / 2,
      rotationY: 0,
      rotationZ: -math.pi / 2,
    );
    final northArrow = await loadArrow(
      "north_zh",
      three.Vector3(0, 0, -gapK),
      rotationX: -math.pi / 2,
      rotationY: 0,
      rotationZ: math.pi,
    );
    final southArrow = await loadArrow(
      "south_zh",
      three.Vector3(0, 0, gapK),
      rotationX: -math.pi / 2,
      rotationY: 0,
      rotationZ: 0,
    );
    final eastArrow = await loadArrow(
      "east_zh",
      three.Vector3(gapK, 0, 0),
      rotationX: -math.pi / 2,
      rotationY: 0,
      rotationZ: math.pi * 1 / 2,
    );
    fixedArrowGroup = three.Group();
    fixedArrowGroup.add(westArrow);
    fixedArrowGroup.add(eastArrow);
    fixedArrowGroup.add(northArrow);
    fixedArrowGroup.add(southArrow);
    fixedArrowGroup.position.setValues(0, 13.5, 0);
    threeJs.scene.add(fixedArrowGroup);

    threeJs.addAnimationEvent((dt) {
      controls.update();
    });
  }

  // 加载
  List<String> genCubeUrls(prefix, postfix) {
    return [
      '${prefix}px$postfix',
      '${prefix}nx$postfix',
      '${prefix}py$postfix',
      '${prefix}ny$postfix',
      '${prefix}pz$postfix',
      '${prefix}nz$postfix',
    ];
  }

  Future<three.Mesh> loadArrow(
    String name,
    three.Vector3 position, {
    required double rotationX,
    required double rotationY,
    required double rotationZ,
  }) async {
    final textureLoader = three.TextureLoader();
    final arrowTexture = await textureLoader.fromAsset(
      'assets/images/direction_$name.png',
    );
    final geometry = three.PlaneGeometry(1, 1);
    final material = three.MeshBasicMaterial({
      MaterialProperty.map: arrowTexture,
      MaterialProperty.transparent: true,
      MaterialProperty.side: three.DoubleSide,
    });
    final mesh = three.Mesh(geometry, material);
    mesh.position = position;
    mesh.scale = three.Vector3(scaleMesh, scaleMesh, scaleMesh);
    mesh.rotateX(rotationX);
    mesh.rotateY(rotationY);
    mesh.rotateZ(rotationZ);
    return mesh;
  }
}
